package com.whut.provider;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author fd
 */
public final class CodeGenerator {

    private CodeGenerator() {

    }

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    private static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in, "UTF-8");
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {
        boolean override = scanner("覆盖已有文件Y/N?").toUpperCase().equals("Y") ? true : false;
        String tableNames = scanner("表名");
        if (!StringUtils.isEmpty(tableNames)) {
            Arrays.stream(tableNames.split(",")).forEach(tb -> {
                if (!StringUtils.isEmpty(tb)) {
                    System.out.println("================准备生成为表【" + tb + "】生成文件！=====================");
                    generate(override, tb);
                }
            });
        }
    }

    private static void generate(boolean override, String tableName) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        System.out.println(System.getProperties());
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        final String projectPath = System.getProperty("user.dir");
        //生成文件的输出目录
        gc.setOutputDir(projectPath + "/smart-track-provider/src/main/java");
        gc.setAuthor("author");
        gc.setOpen(false);
        gc.setFileOverride(override);
        //gc.setActiveRecord(true);
        //开启 baseColumnList 生成通用sql字段
        gc.setBaseColumnList(true);
        //开启 BaseResultMap
        gc.setBaseResultMap(true);
        //指定生成的主键的ID类型
        gc.setIdType(IdType.ID_WORKER);
        //时间类型对应策略
        gc.setDateType(DateType.TIME_PACK);
        //开启 swagger2 模式
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        dataSourceConfig(mpg);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.whut");
        pc.setModuleName("provider");
        //mapper包名
        pc.setMapper("dao");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/smart-track-provider/src/main/resources/mapper/"
                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        mpg.setTemplate(new TemplateConfig().setXml(null));

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel); //数据库表映射到实体的，命名策略
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        //strategy.setSuperControllerClass("com.nz.xplat.common.BaseController");
        strategy.setInclude(tableName);
        strategy.setRestControllerStyle(true);
        //驼峰转连字符
        strategy.setControllerMappingHyphenStyle(false);
        strategy.setTablePrefix("dc_");
        //设置自动填充字段
        List<TableFill> fieldList = new ArrayList<>();
        fieldList.add(new TableFill("create_by", FieldFill.INSERT));
        fieldList.add(new TableFill("create_date", FieldFill.INSERT));
        fieldList.add(new TableFill("update_by", FieldFill.INSERT_UPDATE));
        fieldList.add(new TableFill("update_date", FieldFill.INSERT_UPDATE));
        strategy.setTableFillList(fieldList);
        //设置逻辑删除字段
        strategy.setLogicDeleteFieldName("del_flag");
        //是否生成 serialVersionUID
        strategy.setEntitySerialVersionUID(true);
        //是否生成实体时，生成字段注解
        strategy.setEntityTableFieldAnnotationEnable(true);

        mpg.setStrategy(strategy);
        // 选择 freemarker 引擎需要指定如下加，注意 pom 依赖必须有！
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

    /**
     * 数据源配置
     *
     * @param generator
     */
    private static void dataSourceConfig(AutoGenerator generator) {
        DataSourceConfig dsc = new DataSourceConfig();
        try {
            //InputStream in = ClassLoader.getSystemResourceAsStream("generator.properties");
            //Properties properties = new Properties();
            //properties.load(in);
            YamlPropertySourceLoader resourceLoader = new YamlPropertySourceLoader();
            List<PropertySource<?>> ps = resourceLoader.load("application",
                    new ClassPathResource("application" + ".yml"));
            PropertySource properties = ps.get(0);

            // dsc.setSchemaName("public");
            dsc.setUrl(properties.getProperty("spring.datasource.url").toString());
            dsc.setDriverName(properties.getProperty("spring.datasource.driver-class-name").toString());
            dsc.setUsername(properties.getProperty("spring.datasource.username").toString());
            dsc.setPassword(properties.getProperty("spring.datasource.password").toString());
            generator.setDataSource(dsc);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
